package org.melord.cap;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class HostsManager {
	Global global;
	List<Group> groups;
	List<Host> hosts = new ArrayList<Host>();

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HostsManager manager = new HostsManager();
		try {
			manager.parse("hosts.xml");
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(manager.global);
	}

	public List<Host> getHosts() {
		return hosts;
	}

	public Document parse(String path) throws DocumentException {
		SAXReader reader = new SAXReader();
		// reader.setValidation(true);
		org.dom4j.Document document = reader.read(path);
		global = getGlobal(document);
		groups = getGroups(document);
		hosts = getHosts(document, groups);
		return document;
	}

	public Global getGlobal(Document doc) {
		Global global = null;
		Element ele = doc.getRootElement().element("global");
		if (ele != null) {
			global = new Global();
			setControl(ele, global);
		}
		return global;
	}

	public java.util.List<Group> getGroups(Document doc) {
		ArrayList<Group> result = new ArrayList<Group>();
		List<Element> list = doc.getRootElement().elements("group");
		for (Element g : list) {
			Group group = new Group();
			setControl(g, group);
			group.setName(g.attributeValue("name"));
			result.add(group);
		}
		return result;
	}

	private long getLong(Element e, String name) {
		long t = 0;

		String timeStr = e.elementText(name);
		if (timeStr != null) {
			try {
				t = Long.parseLong(timeStr);
			} catch (Exception ex) {
				// TODO: handle exception
			}
		}
		return t;
	}

	private void setControl(Element e, Global control) {
		control.setText(e.elementText("text"));
		control.setTime(getLong(e, "time"));
		control.setWarnBegin(getLong(e, "warn-time"));
		control.setWarnInterval(getLong(e, "warn-interval"));
		control.setUrlPrefix(e.elementText("url-prefix"));
	}

	public List<Host> getHosts(Document doc, List<Group> groups) {
		ArrayList<Host> result = new ArrayList<Host>();
		Element urls = doc.getRootElement().element("control-urls");
		if (urls == null) {
			return result;
		}
		List<Element> list = urls.elements("control-url");
		for (Element e : list) {
			Host h = new Host();
			h.setUrl(e.elementText("url-name"));
			List<Element> ctrlElements = e.elements("control");
			List<Control> ctrls = new ArrayList<Control>();
			for (Element ctrlElement : ctrlElements) {
				Control ctrl = new Control();
				setControl(ctrlElement, ctrl);
				ctrl.setContext(ctrlElement.elementText("context"));
				ctrls.add(ctrl);
				String gname = ctrlElement.attributeValue("group");
				for (Group g : groups) {
					if (g.getName() != null && g.getName().equals(gname)) {
						ctrl.setGroup(g);
						break;
					}
				}
				ctrl.setGlobal(global);
			}
			h.setControls(ctrls);
			h.setRemindText(e.elementText("context-remind-text"));

			// reminds
			List<String> reminds = new ArrayList<String>();
			Element temp = e.element("context-remind");
			if (temp != null) {
				List<Element> remindElements = temp.elements("remind");
				for (Element remindEle : remindElements) {
					reminds.add(remindEle.getText());
				}
			}
			h.setReminds(reminds);
			result.add(h);
		}
		return result;
	}

	public void write(Document document) throws IOException {

		// lets write to a file
		XMLWriter writer = new XMLWriter(new FileWriter("output.xml"));
		writer.write(document);
		writer.close();

		// Pretty print the document to System.out
		OutputFormat format = OutputFormat.createPrettyPrint();
		writer = new XMLWriter(System.out, format);
		writer.write(document);

		// Compact format to System.out
		format = OutputFormat.createCompactFormat();
		writer = new XMLWriter(System.out, format);
		writer.write(document);
	}
}

class Global {
	protected String text;
	protected long time;
	protected long warnBegin;
	protected long warnInterval;
	protected String urlPrefix;

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public long getTime() {
		return time;
	}

	public void setTime(long time) {
		this.time = time;
	}

	public long getWarnBegin() {
		return warnBegin;
	}

	public void setWarnBegin(long warnBegin) {
		this.warnBegin = warnBegin;
	}

	public long getWarnInterval() {
		return warnInterval;
	}

	public void setWarnInterval(long warnInterval) {
		this.warnInterval = warnInterval;
	}

	public void setUrlPrefix(String urlPrefix) {
		this.urlPrefix = urlPrefix;
	}

	public String getUrlPrefix() {
		return urlPrefix;
	}

	@Override
	public String toString() {
		return String.format("%s,%d,%d,%d,%s", text, time, warnBegin,
				warnInterval, urlPrefix);
	}
}

class Group extends Global {
	private String name;

	protected Global global;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setGlobal(Global global) {
		this.global = global;
	}

	public Global getGlobal() {
		return global;
	}

	@Override
	public String toString() {
		return String.format("%s[%s,%d,%d,%d,%s]", name, text, time, warnBegin,
				warnInterval, urlPrefix);
	}
}

class Control extends Global {
	protected Group group;
	protected Global global;
	private String context;

	public Group getGroup() {
		return group;
	}

	public void setGroup(Group group) {
		this.group = group;
	}

	public void setGlobal(Global global) {
		this.global = global;
	}

	public Global getGlobal() {
		return global;
	}

	public String getContext() {
		return context;
	}

	public void setContext(String context) {
		this.context = context;
	}

	@Override
	public String toString() {
		return String.format("(%s,%s,%d,%d,%d,%s)g=%s,g=%s", text, context,
				time, warnBegin, warnInterval, urlPrefix, group, global);
	}
}

class Host {
	private List<Control> controls = new ArrayList<Control>();
	private String url;
	private String remindText;
	private List<String> reminds = new ArrayList<String>();
	private HttpRequest httpRequest;

	public HttpRequest getHttpRequest() {
		return httpRequest;
	}

	public void setHttpRequest(HttpRequest httpRequest) {
		this.httpRequest = httpRequest;
	}

	public List<Control> getControls() {
		return controls;
	}

	public void setControls(List<Control> controls) {
		this.controls = controls;
	}

	public String getUrl() {
		if (url == null) {
			return "null";
		}
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getRemindText() {
		if (remindText == null) {
			return "null";
		}
		return remindText;
	}

	public void setRemindText(String remindText) {
		this.remindText = remindText;
	}

	public List<String> getReminds() {
		return reminds;
	}

	public void setReminds(List<String> reminds) {
		this.reminds = reminds;
	}

	public boolean match(String host) {
		if (url.contains("*")) {
			String p = url.replaceAll("\\.", "\\\\.").replaceAll("\\*", "\\.*")
					.replaceAll("\\?", "\\\\?");
			// System.out.println(p);
			boolean b = Pattern.compile(p).matcher(host).find();
			return b;
		}
		if (host == null) {
			return false;
		}
		return host.contains(url);
	}

	@Override
	public String toString() {
		return String.format("%s-%s", super.toString(), url);
	}

	public static void main(String[] args) {
		Host h = new Host();
		h.setUrl("http://www.melord.org/abc?p=5&id=6");
		System.out.println(h.match("http://www.melord.org/abc?p=5&id=6d"));
	}
}
